#include "myhead.h"

/*
	tcp双向通信
	服务器的代码
	使用多路复用的关键点：思考清除代码中究竟需要监测哪些文件描述符
	                      监测键盘+监测新的套接字
*/


int main(int argc,char **argv)
{
	int tcpsock;
	int newsock;
	int ret;
	char rbuf[100];
	char buf[100];
	//定义ipv4地址结构体变量存放绑定的ip和端口号
	struct sockaddr_in bindaddr;
	bzero(&bindaddr,sizeof(bindaddr));
	bindaddr.sin_family=PF_INET;
	bindaddr.sin_addr.s_addr=inet_addr("192.168.19.3"); //绑定女朋友自己的ip，需要转换大小端
	bindaddr.sin_port=htons(atoi(argv[1])); //绑定女朋友自己的端口号
	
	//定义ipv4地址结构体变量存放对方(客户端)的ip和端口号
	struct sockaddr_in boyaddr;
	int addrsize=sizeof(boyaddr);
	
	//创建tcp套接字
	tcpsock=socket(AF_INET,SOCK_STREAM,0);
	if(tcpsock==-1)
	{
		perror("创建tcp失败");
		return -1;
	}
	printf("旧的套接字是:%d\n",tcpsock);
	//绑定ip和端口号
	ret=bind(tcpsock,(struct sockaddr *)&bindaddr,sizeof(bindaddr));
	if(ret==-1)
	{
		perror("绑定失败!\n");
		return -1;
	}
	
	//监听
	ret=listen(tcpsock,7);
	if(ret==-1)
	{
		perror("监听失败!\n");
		return -1;
	}
	
	//接受客户端的连接请求
	newsock=accept(tcpsock,(struct sockaddr *)&boyaddr,&addrsize);
	if(newsock==-1)
	{
		perror("接收连接失败!\n");
		return -1;
	}
	
	//定义文件描述符集合变量
	fd_set myset;
	
	//调用select去监测
	while(1)
	{
		//清空集合
		FD_ZERO(&myset);
		//往集合中添加我要监测的文件描述符
		FD_SET(0,&myset); //添加键盘
		FD_SET(newsock,&myset); //添加新的套接字
		printf("如果你不敲键盘，对方也不给你发送信息过来，会一直阻塞在select的位置!\n");
		ret=select(newsock+1,&myset,NULL,NULL,NULL);
		if(ret>0) //监测成功
		{
			//判断键盘在不在集合
			if(FD_ISSET(0,&myset)) //说明你从键盘输入了内容,键盘发生了读就绪
			{
				printf("同学，键盘真的发生了读就绪!!!\n");
				bzero(buf,100);
				scanf("%s",buf);
				send(newsock,buf,strlen(buf),0);
			}
			//判断新的套接字在不在集合
			if(FD_ISSET(newsock,&myset)) //说明新的套接字发生了读就绪(有数据来了，可读)
			{
				//接收客户端发送过来的信息
				bzero(rbuf,100);
				recv(newsock,rbuf,100,0);
				printf("客户端发送过来的信息是：%s\n",rbuf);
			}
		}
		else if(ret<0)
		{
			perror("select失败");
			return -1;
		}
	}


	//关闭
	close(tcpsock);
	return 0;
}